package com.dayatang.product.webapp.spring;

import java.beans.PropertyVetoException;
import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.dayatang.domain.EntityRepository;
import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableTransactionManagement
@ImportResource(value = {"classpath*:applicationContext-annotation.xml", "classpath*:applicationContext-quartz.xml", "classpath*:applicationContext-other.xml"})
public class PersistenceHibernateConfig {
	
	@Value("${jdbc.driverClassName}")
	private String driverClassName;

	@Value("${jdbc.url}")
	private String url;

	@Value("${jdbc.username}")
	private String username;

	@Value("${jdbc.password}")
	private String password;

	@Value("${hibernate.dialect}")
	String hibernateDialect;

	@Value("${hibernate.hbm2ddl.auto}")
	String hibernateHbm2ddlAuto;
	
	public PersistenceHibernateConfig() {
		super();
	}
	
	@Bean
	public AnnotationSessionFactoryBean sessionFactory() {
		final AnnotationSessionFactoryBean annotationSessionFactoryBean = new AnnotationSessionFactoryBean();
		annotationSessionFactoryBean.setDataSource(dataSource());
		annotationSessionFactoryBean.setPackagesToScan(new String[] { "com.dayatang.product.domain" });
		annotationSessionFactoryBean.setHibernateProperties(additionlProperties());
		return annotationSessionFactoryBean;
	}
	
	@Bean
	public DataSource dataSource() {
		final ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
		try {
			comboPooledDataSource.setDriverClass(driverClassName);
		} catch (PropertyVetoException e) {
			throw new DataAccessResourceFailureException("Cannot access JDBC Driver: " + driverClassName, e);
		}
		comboPooledDataSource.setJdbcUrl(url);
		comboPooledDataSource.setUser(username);
		comboPooledDataSource.setPassword(password);
		comboPooledDataSource.setMinPoolSize(10);
		comboPooledDataSource.setMaxPoolSize(300);
		comboPooledDataSource.setInitialPoolSize(10);
		comboPooledDataSource.setAcquireIncrement(5);
		comboPooledDataSource.setMaxStatements(0);
		comboPooledDataSource.setIdleConnectionTestPeriod(60);
		comboPooledDataSource.setAcquireRetryAttempts(30);
		comboPooledDataSource.setBreakAfterAcquireFailure(false);
		comboPooledDataSource.setTestConnectionOnCheckout(false);
		return comboPooledDataSource;
	}
	
	private final Properties additionlProperties() {
		Properties properties = new Properties();
		properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
		return properties;
	}
	
	@Bean
	public PlatformTransactionManager transactionManager() {
		final HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
		hibernateTransactionManager.setSessionFactory(sessionFactory().getObject());
		return hibernateTransactionManager;
	}
	
	@Bean
	public EntityRepository repository() {
		return new com.dayatang.hibernate.EntityRepositoryHibernate(sessionFactory().getObject());
	}
}
